import type { IProjectAnalysis } from '../types/analysis';
import { EnvironmentConfig } from '../utils/environment';
import { analysisStore } from '../stores/analysis-store';

/**
 * 分析数据服务
 */
export class AnalysisDataService {
  private static _instance: AnalysisDataService | null = null;
  private _analysisData: IProjectAnalysis | null = null;
  private _loadingPromises: Map<string, Promise<IProjectAnalysis>> = new Map();
  private _cache: Map<string, { data: IProjectAnalysis; timestamp: number }> = new Map();
  private _cacheExpireTime: number = 5 * 60 * 1000; // 5分钟缓存过期时间

  private constructor() {
    // 根据环境变量设置缓存过期时间
    const cacheMinutes = EnvironmentConfig.getCacheExpireTime();
    this._cacheExpireTime = cacheMinutes * 60 * 1000;

    // 定期清理过期缓存
    if (EnvironmentConfig.isCacheEnabled()) {
      setInterval(() => {
        this.cleanExpiredCache();
      }, this._cacheExpireTime / 2); // 每半个过期时间清理一次
    }
  }

  /**
   * 检查缓存是否有效
   * @param filePath - 文件路径
   * @returns 是否有效
   */
  private isCacheValid(filePath: string): boolean {
    const cached = this._cache.get(filePath);
    if (!cached) return false;

    const now = Date.now();
    return now - cached.timestamp < this._cacheExpireTime;
  }

  /**
   * 从缓存获取数据
   * @param filePath - 文件路径
   * @returns 缓存的数据
   */
  private getCachedData(filePath: string): IProjectAnalysis | null {
    if (this.isCacheValid(filePath)) {
      const cached = this._cache.get(filePath);
      return cached?.data || null;
    }
    return null;
  }

  /**
   * 设置缓存数据
   * @param filePath - 文件路径
   * @param data - 数据
   */
  private setCachedData(filePath: string, data: IProjectAnalysis): void {
    this._cache.set(filePath, {
      data,
      timestamp: Date.now(),
    });
  }

  /**
   * 清理过期缓存
   */
  private cleanExpiredCache(): void {
    const now = Date.now();
    for (const [key, cached] of this._cache.entries()) {
      if (now - cached.timestamp >= this._cacheExpireTime) {
        this._cache.delete(key);
      }
    }
  }

  /**
   * 获取分析数据文件路径
   * @returns 分析数据文件路径
   */
  private getAnalysisDataPath(): string {
    const envPath = EnvironmentConfig.getAnalysisDataPath();
    console.log(`使用环境变量中的分析数据路径: ${envPath}`);
    return envPath;
  }

  /**
   * 检查分析数据文件是否存在
   * @param filePath - 文件路径
   * @returns 是否存在
   */
  private async checkFileExists(filePath: string): Promise<boolean> {
    try {
      const response = await fetch(filePath, { method: 'HEAD' });
      return response.ok;
    } catch {
      return false;
    }
  }

  /**
   * 获取单例实例
   * @returns 分析数据服务实例
   */
  static getInstance(): AnalysisDataService {
    if (!this._instance) {
      this._instance = new AnalysisDataService();
    }
    return this._instance;
  }

  /**
   * 加载分析数据
   * @param filePath - 分析结果文件路径（可选，默认从环境变量获取）
   * @returns 分析数据
   */
  async loadAnalysisData(filePath?: string): Promise<IProjectAnalysis> {
    const dataPath = filePath || this.getAnalysisDataPath();

    // 设置加载状态和当前路径
    analysisStore.setLoading(true);
    analysisStore.setCurrentFilePath(dataPath);

    try {
      // 如果缓存被禁用，直接加载
      if (!EnvironmentConfig.isCacheEnabled()) {
        console.log('缓存已禁用，直接加载数据');
        const data = await this._loadAnalysisDataInternal(dataPath);
        this._analysisData = data;
        return data;
      }

      // 检查缓存
      const cachedData = this.getCachedData(dataPath);
      if (cachedData) {
        console.log(`使用缓存数据: ${dataPath}`);
        this._analysisData = cachedData;
        return cachedData;
      }

      // 检查是否正在加载
      const existingPromise = this._loadingPromises.get(dataPath);
      if (existingPromise) {
        console.log(`等待正在进行的请求: ${dataPath}`);
        return existingPromise;
      }

      // 创建新的加载Promise
      const loadingPromise = this._loadAnalysisDataInternal(dataPath);

      // 存储Promise到加载队列
      this._loadingPromises.set(dataPath, loadingPromise);

      const result = await loadingPromise;

      // 加载完成，设置缓存
      this.setCachedData(dataPath, result);
      this._analysisData = result;

      // 清理过期缓存
      this.cleanExpiredCache();

      return result;
    } catch (error) {
      // 加载失败，从队列中移除
      throw error;
    } finally {
      // 无论成功失败，都要从加载队列中移除并更新状态
      this._loadingPromises.delete(dataPath);
      analysisStore.setLoading(false);
    }
  }  /**
   * 内部加载数据方法
   * @param dataPath - 数据路径
   * @returns 分析数据
   */
  private async _loadAnalysisDataInternal(dataPath: string): Promise<IProjectAnalysis> {
    try {
      console.log(`开始加载分析数据: ${dataPath}`);

      // 检查文件是否存在
      const fileExists = await this.checkFileExists(dataPath);
      if (!fileExists) {
        console.warn(`分析数据文件不存在: ${dataPath}`);

        // 尝试备用路径（但不使用相同的缓存key）
        const fallbackPath = '/analysis/test-analysis.json';
        if (dataPath !== fallbackPath) {
          const fallbackExists = await this.checkFileExists(fallbackPath);

          if (!fallbackExists) {
            throw new Error(`分析数据文件不存在: ${dataPath} 和 ${fallbackPath}`);
          }

          console.log(`使用备用分析数据文件: ${fallbackPath}`);

          // 递归调用，使用备用路径（这会创建新的缓存条目）
          return this.loadAnalysisData(fallbackPath);
        }

        throw new Error(`分析数据文件不存在: ${dataPath}`);
      }

      const response = await fetch(dataPath);
      if (!response.ok) {
        throw new Error(`加载分析数据失败: ${response.statusText}`);
      }

      const data = await response.json();

      console.log(`成功加载分析数据: ${dataPath}`, {
        项目名称: data.projectName,
        包数量: data.packages?.length || 0,
        文件数量: data.statistics?.totalFiles || 0,
        缓存状态: '新加载'
      });

      return data;
    } catch (error) {
      console.error('加载分析数据失败:', error);
      throw error;
    }
  }

  /**
   * 获取当前分析数据
   * @returns 当前分析数据
   */
  getCurrentAnalysisData(): IProjectAnalysis | null {
    return this._analysisData;
  }

  /**
   * 清除缓存
   * @param filePath - 可选的文件路径，如果不提供则清除所有缓存
   */
  clearCache(filePath?: string): void {
    if (filePath) {
      this._cache.delete(filePath);
      this._loadingPromises.delete(filePath);
      console.log(`已清除缓存: ${filePath}`);
    } else {
      this._cache.clear();
      this._loadingPromises.clear();
      console.log('已清除所有缓存');
    }
  }

  /**
   * 获取缓存统计信息
   * @returns 缓存统计
   */
  getCacheStats(): {
    cacheSize: number;
    activeLoading: number;
    cacheKeys: string[];
    loadingKeys: string[];
  } {
    return {
      cacheSize: this._cache.size,
      activeLoading: this._loadingPromises.size,
      cacheKeys: Array.from(this._cache.keys()),
      loadingKeys: Array.from(this._loadingPromises.keys()),
    };
  }

  /**
   * 预加载数据
   * @param filePaths - 要预加载的文件路径列表
   * @returns 预加载结果
   */
  async preloadData(filePaths: string[]): Promise<{
    success: string[];
    failed: { path: string; error: string }[];
  }> {
    const success: string[] = [];
    const failed: { path: string; error: string }[] = [];

    const loadPromises = filePaths.map(async (filePath) => {
      try {
        await this.loadAnalysisData(filePath);
        success.push(filePath);
      } catch (error) {
        failed.push({
          path: filePath,
          error: error instanceof Error ? error.message : '未知错误',
        });
      }
    });

    await Promise.allSettled(loadPromises);

    console.log(`预加载完成 - 成功: ${success.length}, 失败: ${failed.length}`);

    return { success, failed };
  }

  /**
   * 获取项目概览数据
   * @returns 项目概览
   */
  getProjectOverview(): {
    name: string;
    type: string;
    packages: number;
    files: number;
    dependencies: number;
    analysisTime: string;
  } | null {
    if (!this._analysisData) return null;

    return {
      name: this._analysisData.projectName,
      type: this._analysisData.isMonorepo ? 'Monorepo' : '单一仓库',
      packages: this._analysisData.packages.length,
      files: this._analysisData.statistics.totalFiles,
      dependencies: this._analysisData.statistics.totalDependencies,
      analysisTime: new Date(this._analysisData.analysisTime).toLocaleString(),
    };
  }

  /**
   * 获取依赖类型统计
   * @returns 依赖类型统计数据
   */
  getDependencyTypeStats(): Array<{ name: string; value: number; type: string }> | null {
    if (!this._analysisData) return null;

    const typeStats = {
      local: 0,
      package: 0,
      workspace: 0,
      root: 0,
    };

    // 统计所有文件的依赖类型
    for (const pkg of this._analysisData.packages) {
      for (const file of pkg.files) {
        for (const dep of file.dependencies) {
          typeStats[dep.type]++;
        }
      }
    }

    return [
      { name: '本地文件', value: typeStats.local, type: 'local' },
      { name: 'NPM 包', value: typeStats.package, type: 'package' },
      { name: '工作空间包', value: typeStats.workspace, type: 'workspace' },
      { name: '根目录引用', value: typeStats.root, type: 'root' },
    ].filter(item => item.value > 0);
  }

  /**
   * 获取包依赖关系数据（用于关系图）
   * @param includeRootPackage - 是否包含根包，默认 false
   * @returns 包依赖关系数据
   */
  getPackageDependencyGraph(includeRootPackage = false): {
    nodes: Array<{ id: string; name: string; type: string; value: number; category: number; itemStyle?: any }>;
    links: Array<{ source: string; target: string; value: number; lineStyle?: any }>;
    categories: Array<{ name: string }>;
  } | null {
    if (!this._analysisData) return null;

    const nodes: Array<{ id: string; name: string; type: string; value: number; category: number; itemStyle?: any }> = [];
    const links: Array<{ source: string; target: string; value: number; lineStyle?: any }> = [];
    const categories = [
      { name: '工作空间包' },
      { name: '根包' },
    ];

    // 过滤包（可选择是否包含根包）
    const filteredPackages = this._analysisData.packages.filter(pkg =>
      includeRootPackage || pkg.type !== 'root'
    );

    // 如果过滤后没有包，返回 null
    if (filteredPackages.length === 0) {
      return null;
    }

    // 构建节点
    for (const pkg of filteredPackages) {
      const isWorkspacePackage = pkg.type === 'workspace';
      const nodeColor = isWorkspacePackage ? '#409EFF' : '#67C23A';

      nodes.push({
        id: pkg.name,
        name: pkg.name,
        type: pkg.type,
        value: pkg.files.length,
        category: isWorkspacePackage ? 0 : 1,
        itemStyle: {
          color: nodeColor,
          borderColor: '#ffffff',
          borderWidth: 2,
          shadowBlur: 8,
          shadowColor: 'rgba(0, 0, 0, 0.3)',
        }
      });
    }

    // 构建包名集合，用于快速查找
    const packageNames = new Set(filteredPackages.map(p => p.name));

    // 构建链接
    for (const pkg of filteredPackages) {
      for (const depPackage of pkg.packageDependencies) {
        // 只有当目标包也在过滤后的包列表中时，才创建链接
        if (packageNames.has(depPackage)) {
          // 根据依赖关系类型设置不同的线条样式
          const sourcePackage = filteredPackages.find(p => p.name === pkg.name);
          const targetPackage = filteredPackages.find(p => p.name === depPackage);

          let linkColor = '#999999';
          let linkWidth = 2;
          let linkOpacity = 0.6;

          if (sourcePackage?.type === 'workspace' && targetPackage?.type === 'workspace') {
            linkColor = '#409EFF'; // 工作空间包之间的依赖 - 蓝色
            linkWidth = 3;
            linkOpacity = 0.8;
          } else if (sourcePackage?.type === 'workspace' && targetPackage?.type === 'root') {
            linkColor = '#E6A23C'; // 工作空间包依赖根包 - 橙色
            linkWidth = 2;
            linkOpacity = 0.7;
          } else if (sourcePackage?.type === 'root' && targetPackage?.type === 'workspace') {
            linkColor = '#F56C6C'; // 根包依赖工作空间包（通常不应该出现）- 红色
            linkWidth = 2;
            linkOpacity = 0.7;
          }

          links.push({
            source: pkg.name,
            target: depPackage,
            value: 1,
            lineStyle: {
              color: linkColor,
              width: linkWidth,
              opacity: linkOpacity,
              curveness: 0.1, // 减少弯曲，让线条更直
              type: sourcePackage?.type === 'workspace' && targetPackage?.type === 'workspace' ? 'solid' : 'dashed',
            }
          });
        }
      }
    }

    return { nodes, links, categories };
  }

  /**
   * 获取热力图数据（包的文件数量和依赖数量）
   * @returns 热力图数据
   */
  getPackageHeatmapData(): Array<[number, number, number]> | null {
    if (!this._analysisData) return null;

    return this._analysisData.packages.map((pkg, index) => [
      index,
      0,
      pkg.files.length + pkg.packageDependencies.length
    ]);
  }
}
